<template>
  <div class="image-style-panel">
    <div class="origin-image" :style="{
      backgroundImage: `url(${handleElement.src})`,
      transform: `rotateX(${handleElement.flipV ? 180 : 0}deg) rotateY(${handleElement.flipH ? 180 : 0}deg)`
    }"></div>
    <ElementFlip />

    <ButtonGroup class="row">
      <Button style="flex: 5;" @click="clipImage()">
        <IconTailoring class="btn-icon" /> 裁剪图片
      </Button>
      <Popover trigger="click" placement="topRight" v-model:visible="clipPanelVisible">
        <template #content>
          <div class="clip">
            <div class="title">按形状：</div>
            <div class="shape-clip">
              <div class="shape-clip-item" v-for="(item, key) in shapeClipPathOptions" :key="key"
                @click="presetImageClip(key)">
                <div class="shape" :style="{ clipPath: item.style }"></div>
              </div>
            </div>

            <template v-for="type in ratioClipOptions" :key="type.label">
              <div class="title" v-if="type.label">按{{ type.label }}：</div>
              <ButtonGroup class="row">
                <Button style="flex: 1;" v-for="item in type.children" :key="item.key"
                  @click="presetImageClip('rect', item.ratio)">{{ item.key }}</Button>
              </ButtonGroup>
            </template>
          </div>
        </template>
        <Button class="no-padding" style="flex: 1;">
          <IconDown />
        </Button>
      </Popover>
    </ButtonGroup>

    <Divider />
    <ElementFilter />
    <Divider />
    <ElementOutline />
    <Divider />
    <ElementShadow />
    <Divider />

    <!-- <FileInput @change="files => replaceImage(files)"> -->
    <Button class="full-width-btn" @click="openMediaLibrary">
      <IconTransform class="btn-icon" /> 替换图片
    </Button>
    <!-- </FileInput> -->
    <Button class="full-width-btn" @click="resetImage()">
      <IconUndo class="btn-icon" /> 重置样式
    </Button>
    <Button class="full-width-btn" @click="setBackgroundImage()">
      <IconTheme class="btn-icon" />
      <span v-if='backgroundVisible'>取消背景</span>
      <span v-else>设为背景</span>
    </Button>
    <Divider />
    <ElementWidthHeight />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, watch, onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTImageElement, SlideBackground } from '@/types/slides'
import { CLIPPATHS } from '@/configs/imageClip'
import { getImageDataURL } from '@/utils/image'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'

import ElementOutline from '../common/ElementOutline.vue'
import ElementShadow from '../common/ElementShadow.vue'
import ElementWidthHeight from '../common/ElementWidthHeight.vue'
import ElementFlip from '../common/ElementFlip.vue'
import ElementFilter from '../common/ElementFilter.vue'

import { useEditorStore } from '@/store'
const editorStore = useEditorStore()
const { mediaCategroy } = storeToRefs(useEditorStore())

const shapeClipPathOptions = CLIPPATHS
const ratioClipOptions = [
  {
    label: '纵横比（方形）',
    children: [
      { key: '1:1', ratio: 1 / 1 },
    ],
  },
  {
    label: '纵横比（纵向）',
    children: [
      { key: '2:3', ratio: 3 / 2 },
      { key: '3:4', ratio: 4 / 3 },
      { key: '3:5', ratio: 5 / 3 },
      { key: '4:5', ratio: 5 / 4 },
    ],
  },
  {
    label: '纵横比（横向）',
    children: [
      { key: '3:2', ratio: 2 / 3 },
      { key: '4:3', ratio: 3 / 4 },
      { key: '5:3', ratio: 3 / 5 },
      { key: '5:4', ratio: 4 / 5 },
    ],
  },
  {
    children: [
      { key: '16:9', ratio: 9 / 16 },
      { key: '16:10', ratio: 10 / 16 },
    ],
  },
]

export default defineComponent({
  name: 'image-style-panel',
  components: {
    ElementOutline,
    ElementShadow,
    ElementFlip,
    ElementFilter,
    ElementWidthHeight,
  },
  setup() {
    const mainStore = useMainStore()
    const slidesStore = useSlidesStore()
    const { handleElement, handleElementId } = storeToRefs(mainStore)
    const { currentSlide } = storeToRefs(slidesStore)
    const clipPanelVisible = ref(false)
    const backgroundVisible = ref(false)
    const { addHistorySnapshot } = useHistorySnapshot()

    // 打开自由裁剪
    const clipImage = () => {
      mainStore.setClipingImageElementId(handleElementId.value)
      clipPanelVisible.value = false
    }

    // 获取原始图片的位置大小
    const getImageElementDataBeforeClip = () => {
      const _handleElement = handleElement.value as PPTImageElement

      // 图片当前的位置大小和裁剪范围
      const imgWidth = _handleElement.width
      const imgHeight = _handleElement.height
      const imgLeft = _handleElement.left
      const imgTop = _handleElement.top
      const originClipRange: [[number, number], [number, number]] = _handleElement.clip ? _handleElement.clip.range : [[0, 0], [100, 100]]

      const originWidth = imgWidth / ((originClipRange[1][0] - originClipRange[0][0]) / 100)
      const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100)
      const originLeft = imgLeft - originWidth * (originClipRange[0][0] / 100)
      const originTop = imgTop - originHeight * (originClipRange[0][1] / 100)

      return {
        originClipRange,
        originWidth,
        originHeight,
        originLeft,
        originTop,
      }
    }

    // 预设裁剪
    const presetImageClip = (shape: string, ratio = 0) => {
      const _handleElement = handleElement.value as PPTImageElement

      const {
        originClipRange,
        originWidth,
        originHeight,
        originLeft,
        originTop,
      } = getImageElementDataBeforeClip()

      // 纵横比裁剪（形状固定为矩形）
      if (ratio) {
        const imageRatio = originHeight / originWidth

        const min = 0
        const max = 100
        let range: [[number, number], [number, number]]

        if (imageRatio > ratio) {
          const distance = ((1 - ratio / imageRatio) / 2) * 100
          range = [[min, distance], [max, max - distance]]
        }
        else {
          const distance = ((1 - imageRatio / ratio) / 2) * 100
          range = [[distance, min], [max - distance, max]]
        }
        slidesStore.updateElement({
          id: handleElementId.value,
          props: {
            clip: { ..._handleElement.clip, shape, range },
            left: originLeft + originWidth * (range[0][0] / 100),
            top: originTop + originHeight * (range[0][1] / 100),
            width: originWidth * (range[1][0] - range[0][0]) / 100,
            height: originHeight * (range[1][1] - range[0][1]) / 100,
          },
        })
      }
      // 形状裁剪（保持当前裁剪范围）
      else {
        slidesStore.updateElement({
          id: handleElementId.value,
          props: {
            clip: { ..._handleElement.clip, shape, range: originClipRange }
          },
        })
      }
      clipImage()
      addHistorySnapshot()
    }

    // 替换图片（保持当前的样式）
    const replaceImage = (files: File[]) => {
      const imageFile = files[0]
      if (!imageFile) return
      getImageDataURL(imageFile).then(dataURL => {
        const props = { src: dataURL }
        slidesStore.updateElement({ id: handleElementId.value, props })
      })
      addHistorySnapshot()
    }

    //替换图片从媒体库
    const openMediaLibrary = () => {
      editorStore.setSourceType('1')

      editorStore.setMediaCategroy('replaceimage')
      editorStore.setCloudToggle(true)
    }

    const resetSource = () => {
      editorStore.setCloudToggle(false)
      editorStore.setSourceUrl('')
      editorStore.setSourceType('')
      editorStore.setAudioUrl('')
      editorStore.setSourcePreview(false)

    }

    const initEvent = () => {
      window.addEventListener(
        "message",
        (e) => {

          if(e.data.source == 'freeeditor') {
          if (e.data.data.length) {
            if (editorStore.mediaCategroy === 'replaceimage') {
              // console.log("替换图片", e.data)

              resetSource()

              let sel = e.data.data[0].fileUrl
              replaceImageFromMedia(sel)
            }

          }
        }
        },
        false
      )
    }

    const replaceImageFromMedia = (dataURL: string) => {
      const props = { src: dataURL }
      slidesStore.updateElement({ id: handleElementId.value, props })
      addHistorySnapshot()
    }

    // 重置图片：清除全部样式
    const resetImage = () => {
      const _handleElement = handleElement.value as PPTImageElement

      if (_handleElement.clip) {
        const {
          originWidth,
          originHeight,
          originLeft,
          originTop,
        } = getImageElementDataBeforeClip()

        slidesStore.updateElement({
          id: handleElementId.value,
          props: {
            left: originLeft,
            top: originTop,
            width: originWidth,
            height: originHeight,
          },
        })
      }

      slidesStore.removeElementProps({
        id: handleElementId.value,
        propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],
      })
      addHistorySnapshot()
    }
    watch(
      () => handleElement.value as PPTImageElement,
      (val: PPTImageElement) => {
        if (currentSlide.value.background?.image === val?.src) {
          backgroundVisible.value = true
        } else {
          backgroundVisible.value = false
        }
      }
    )
    // 将图片设置为背景
    const setBackgroundImage = () => {
      const _handleElement = handleElement.value as PPTImageElement
      // console.log(currentSlide.value, '...currentSlide.value.background', _handleElement)
      const backgroundImage = currentSlide.value.background?.image
      if (backgroundImage === _handleElement.src) {

        const background: SlideBackground = {
          ...currentSlide.value.background,
          type: 'image',
          image: '',
          imageSize: 'cover',
        }
        slidesStore.updateSlide({ background })
        backgroundVisible.value = false
        return
      }
      const background: SlideBackground = {
        ...currentSlide.value.background,
        type: 'image',
        image: _handleElement.src,
        imageSize: 'cover',
      }
      slidesStore.updateSlide({ background })
      backgroundVisible.value = true
      addHistorySnapshot()
    }

    onMounted(() => {

      initEvent()
    })

    return {
      clipPanelVisible,
      shapeClipPathOptions,
      ratioClipOptions,
      handleElement,
      clipImage,
      presetImageClip,
      replaceImage,
      resetImage,
      setBackgroundImage,
      initEvent,
      openMediaLibrary,
      backgroundVisible
    }
  },
})
</script>

<style lang="scss" scoped>
.row {
  width: 100%;
  display: flex;
  align-items: center;
  margin-bottom: 22px;
  border-radius: 6px;
}

.switch-wrapper {
  text-align: right;
}

.origin-image {
  height: 160px;
  border-radius: 6px;
  background-color: $boardBlackColor;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  // background-color: $lightGray;
  margin-bottom: 22px;
}

.full-width-btn {
  width: 100%;
  margin-bottom: 22px;
}

.btn-icon {
  margin-right: 3px;
}

.clip {
  width: 260px;
  font-size: 12px;

  .title {
    margin-bottom: 5px;
  }
}

.shape-clip {
  margin-bottom: 10px;

  @include flex-grid-layout();
}

.shape-clip-item {
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;

  @include flex-grid-layout-children(5, 16%);

  &:hover .shape {
    background-color: #ccc;
  }

  .shape {
    width: 40px;
    height: 40px;
    background-color: #e1e1e1;
  }
}
</style>